package com.zktravel.service.order;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.odianyun.util.BeanUtils;
import com.zktravel.constants.CommonConstant;
import com.zktravel.constants.OrderConstant;
import com.zktravel.constants.ProductConstant;
import com.zktravel.core.exception.VisibleException;
import com.zktravel.enums.CodeEnum;
import com.zktravel.mapper.*;
import com.zktravel.model.dto.cart.CartDTO;
import com.zktravel.model.dto.order.CusOrderMasterDTO;
import com.zktravel.model.dto.user.UserInfo;
import com.zktravel.model.po.*;
import com.zktravel.model.vo.cart.CartVO;
import com.zktravel.model.vo.order.CusOrderAddressVO;
import com.zktravel.model.vo.order.CusOrderMasterTableVO;
import com.zktravel.model.vo.user.ShopVO;
import com.zktravel.service.BaseServiceImpl;
import com.zktravel.service.message.WxMsgService;
import com.zktravel.util.IdcardValidator;
import com.zktravel.util.OrderCodeUtil;
import com.zktravel.util.StringConcatUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CusOrderMasterServiceImpl extends BaseServiceImpl implements CusOrderMasterService {

    @Resource
    private CartMapper cartMapper;
    @Resource
    private ShopMapper shopMapper;
    @Resource
    private CusOrderAddressMapper cusOrderAddressMapper;
    @Resource
    private CusOrderMasterMapper cusOrderMasterMapper;
    @Resource
    private CusOrderDetailMapper cusOrderDetailMapper;
    @Resource
    private CusCouponService cusCouponService;
    @Resource
    private PlProductMapper plProductMapper;
    @Resource
    private CusCouponMapper cusCouponMapper;
    @Resource
    private WxMsgService wxMsgService;

    private static final String CARTLIST = "cartList";
    private static final String LEAVEAMT = "leaveAmt";
    private static final String TOTALAMT = "totalAmt";
    private static final String PAYAMT = "payAmt";
    private static final String POSTAMT = "postAmt";
    private static final String TAXAMT = "taxAmt";
    private static final String ADDRESS = "address";
    private static final String NEEDIDCARD = "needIdCard";

    private static final String PAY_TYPE_WX = "WX_PAY";
    private static final String STATUS_WAIT = "WAIT";

    private static final Integer ORDER_CLOSED = 100; // 已关闭 / 已过期
    private static final Integer ORDER_PENDING = 110; // 待支付
    private static final Integer ORDER_PAYED = 120;   // 已支付
    private static final Integer ORDER_NOT_FOUND = 130; // 无此订单

    /**
     * 检查订单状态
     *
     * @param userId
     * @param orderId
     * @return
     */
    @Override
    public Integer checkOrderStatus(Long userId, Long orderId) {
        CusOrderMaster po = new CusOrderMaster();
        po.setId(orderId);
        CusOrderMaster order = this.cusOrderMasterMapper.selectOne(po);

        if (null == order || 0 != order.getCustomId().compareTo(userId)) {
            return ORDER_NOT_FOUND;
        }

        switch (order.getStatus()) {
            case "WAIT":
                return ORDER_PENDING;
            case "CANCEL":
                return ORDER_CLOSED;
            case "PAID":
            case "SEND":
            case "COMPLETED":
            case "REFUNDED":
                return ORDER_PAYED;
        }

        return ORDER_NOT_FOUND;
    }

    /**
     * @param dto
     * @return 返回类型
     * @throws
     * @Title: getPaymentInfoTailor
     * @Description: B端订单预览
     * @author diaoxingguo
     * @date 2018年6月16日
     */
    @Override
    public Map<String, Object> getPaymentInfoTailor(CusOrderMasterDTO dto, Long shopId, Long userId) {
        return this.getPaymentInfo(dto, CommonConstant.PLATFORM_TYPE_B, true, shopId, userId);
    }

    /**
     * @param dto
     * @return 返回类型
     * @throws
     * @Title: submitOrderWithTx
     * @Description: B端订单提交
     * @author diaoxingguo
     * @date 2018年6月16日
     */
    @Override
    @Transactional
    public CusOrderMasterTableVO submitOrderTailorWithTx(CusOrderMasterDTO dto, Long shopId, Long userId) {
        List<Long> cartIds = dto.getCartIds();
        //用户信息
        UserInfo userInfo = this.getUser(userId);
        Boolean isVip = userInfo.isVip();

        String shopName = userInfo.getShopInfo().getName();
        String userName = userInfo.getCard().getName();

        CusOrderAddressVO addr = dto.getAddress();

        //获取购物车商品信息
        List<CartVO> cartList = this.getCartList(cartIds, userId, addr.getIdCard(), shopId, CommonConstant.PLATFORM_TYPE_B);

        // 获取上级商品的成本
        Map<Long, CartVO> supList = this.getParentProductInfo(shopId, userId, cartIds, CommonConstant.PLATFORM_TYPE_B);

        //删除购物车
        this.deleteCart(shopId, userId, cartIds);

        //商品总价
        BigDecimal totalAmt = BigDecimal.ZERO;
        //邮费
        BigDecimal postAmt = OrderConstant.POST_AMT;
        //税费
        BigDecimal taxAmt = BigDecimal.ZERO;

        //费用计算
        Integer totalNum = 0;
        List<PlProduct> plProductList = Lists.newArrayList();
        for (CartVO vo : cartList) {
            BigDecimal price = vo.getTotalMarketPrice();
            if (isVip && null != vo.getTotalMarketPriceVip()
                    && vo.getTotalMarketPriceVip().compareTo(BigDecimal.ZERO) > 0) {
                price = vo.getTotalMarketPriceVip();
            }
            totalAmt = totalAmt.add(price);
            totalNum = totalNum + vo.getNum();

            PlProduct plProduct = new PlProduct();
            plProduct.setId(vo.getPpid());
            plProduct.setStockNum(vo.getNum());
            plProductList.add(plProduct);
        }

        //总价
        if (totalAmt.compareTo(OrderConstant.EXEMPTION_POSTAGE_B) >= 0) {
            postAmt = BigDecimal.ZERO;
        }

        //更改商品库存和销量
        this.updateStockAndSellNum(plProductList);

        //实付价
        BigDecimal payAmt = totalAmt.add(postAmt);

        Date date = new Date();
        //先保存地址
        CusOrderAddress address = BeanUtils.copyProperties(addr, CusOrderAddress.class);
        address.setUserId(userId);
        address.setCreatedAt(date);
        cusOrderAddressMapper.save(address);

        // 保存order主表
        CusOrderMaster so = this.saveCusOrderMaster(
                userId, shopId, address.getId(), totalAmt, postAmt,
                payAmt, taxAmt, totalNum, dto, null,
                null, CommonConstant.PLATFORM_TYPE_B);

        // B端采购订单 不需要新订单标记
        Long soId = so.getId();
        String orderCode = so.getOrderId();
        //保存order_item表
        List<CusOrderDetail> itemList = Lists.newArrayList();

        String mpName = "";
        for (CartVO vo : cartList) {
            CusOrderDetail soItem = new CusOrderDetail();
            soItem.setPid(soId);
            soItem.setShopId(shopId);
            soItem.setCustomId(userId);
            soItem.setMchName(vo.getName());
            soItem.setPpid(vo.getPpid());
            soItem.setMchImg(vo.getMainImageUrl());
            soItem.setMchDesc(vo.getUnitDesc());
            soItem.setTotalAmt(vo.getTotalMarketPrice());
            soItem.setUnitAmt(vo.getMarketPrice());

            soItem.setSupplierPrice(vo.getMarketPrice());
            soItem.setMarketPrice(vo.getMarketPrice());
            if (isVip && null != vo.getTotalMarketPriceVip()
                    && vo.getTotalMarketPriceVip().compareTo(BigDecimal.ZERO) > 0) {
                soItem.setTotalAmt(vo.getTotalMarketPriceVip());
                soItem.setUnitAmt(vo.getMarketPriceVip());
                soItem.setSupplierPrice(vo.getMarketPriceVip());
            }
            soItem.setTaxAmt(taxAmt);
            soItem.setNum(vo.getNum());
            soItem.setStatus(STATUS_WAIT);
            soItem.setCreatedAt(date);
            soItem.setpShopId(0L);
            soItem.setpProfitAmt(new BigDecimal(0));

            mpName = StringConcatUtils.concatString(mpName, vo.getName(), CommonConstant.CONCAT_LENGTH_30);

            // 超级合伙人利润处理
            this.setSuperProfit(supList, vo, soItem, vo.getNum(), so);
            itemList.add(soItem);
        }
        // 更新主表字段
        this.updateCusOrderMaster(so);

        this.cusOrderDetailMapper.batchInsert(itemList);

        CusOrderMasterTableVO resultSo = this.handleResult(totalAmt, postAmt, payAmt, taxAmt, orderCode,
                address.getId(), shopId, userId, dto.getRemark(), soId, totalNum);

        //异步发送消息
        //管理员消息
        wxMsgService.sendOrderMsgToAdmin(shopName, userName, mpName, totalAmt);
        return resultSo;
    }

    /**
     * @param dto
     * @return 返回类型
     * @throws
     * @Title: getPaymentInfoClient
     * @Description: C端订单预览
     * @author diaoxingguo
     * @date 2018年6月16日
     */
    @Override
    public Map<String, Object> getPaymentInfoClient(CusOrderMasterDTO dto, Long shopId, Long userId) {
        return this.getPaymentInfo(dto, CommonConstant.PLATFORM_TYPE_C, true, shopId, userId);
    }

    private Map<String, Object> getPaymentInfo(CusOrderMasterDTO dto, Integer platformType, Boolean needAddr,
                                               Long shopId, Long userId) {
        List<Long> cartIds = dto.getCartIds();
        Boolean isVip = this.getUser(userId).isVip();
        //需要身份证号
        Boolean needID = true;

        //获取购物车对应的商品信息
        List<CartVO> cartList = this.cartMapper.listProduct(cartIds, userId, shopId, platformType);
        if (CollectionUtils.isEmpty(cartList)) {
            throw new VisibleException(CodeEnum.PRODUCT_NOT_EXIST);
        }

        //如果全部在国内，不需要身份证号
        List<CartVO> outProductList = cartList.stream().filter(item -> ProductConstant.STOCK_AREA_OUT.equals(item.getStockArea())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(outProductList)) {
            needID = false;
        }

        cartList.stream().forEach(vo -> {
            if (vo.getStockNum() < vo.getNum()) {
                throw new VisibleException(CodeEnum.PRODUCT_STOCK_NUM_LT_0.getCode(), vo.getName());
            }
        });

        //商品总价
        BigDecimal totalAmt = BigDecimal.ZERO;
        //优惠总价
        BigDecimal leaveAmt = BigDecimal.ZERO;
        //邮费
        BigDecimal postAmt = OrderConstant.POST_AMT;
        //税费
        BigDecimal taxAmt = BigDecimal.ZERO;

        BigDecimal payAmt = BigDecimal.ZERO;

        Map<Long, CusCoupon> couponMap = Maps.newHashMap();
        //获取优惠券
        if (CommonConstant.PLATFORM_TYPE_C.equals(platformType)) {
            List<Long> tpidList = cartList.stream().map(CartVO::getProductId).collect(Collectors.toList());
            couponMap = cusCouponService.getMapByTpids(tpidList, userId, shopId);
            //获取店主的isvip
            isVip = this.getShopUserInfo(shopId).isVip();
        }

        //费用计算
        for (CartVO vo : cartList) {
            // B端费用计算
            if (CommonConstant.PLATFORM_TYPE_B.equals(platformType)) {
                BigDecimal price = vo.getTotalMarketPrice(); // 成本价
                if (isVip && null != vo.getTotalMarketPriceVip()
                        && vo.getTotalMarketPriceVip().compareTo(BigDecimal.ZERO) > 0) {
                    leaveAmt = leaveAmt.add(vo.getTotalMarketPrice().subtract(vo.getTotalMarketPriceVip()));
                }
                totalAmt = totalAmt.add(price);
                payAmt = payAmt.add(price);
            }

            // C端费用计算
            if (CommonConstant.PLATFORM_TYPE_C.equals(platformType)) {
//                BigDecimal price = (null != vo.getCounterPrice()) ? vo.getCounterPrice() : BigDecimal.ZERO;
                BigDecimal price = vo.getSellPrice().compareTo(vo.getCounterPrice()) >= 0 ? vo.getSellPrice() : vo.getCounterPrice();
                Integer num = (null != vo.getNum()) ? vo.getNum() : 0;
                BigDecimal totalPrice = price.multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP);

                //加优惠券利润计算
                CusCoupon coupon = couponMap.get(vo.getProductId());
                //优惠券判断
                if (null != coupon) {
                    //成本价
                    if (isVip && null != vo.getMarketPriceVip()) {
                        vo.setMarPrice(vo.getMarketPriceVip());
                    } else {
                        vo.setMarPrice(vo.getMarketPrice());
                    }
                    //单个利润计算:售价-优惠券-成本价
                    BigDecimal profitUnitAmt = price.subtract(coupon.getAmt()).subtract(vo.getMarPrice());
                    if (profitUnitAmt.compareTo(BigDecimal.ZERO) > 0) {
                        vo.setCouponAmt(coupon.getAmt());
                        BigDecimal eachLeave = coupon.getAmt().multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        leaveAmt = leaveAmt.add(eachLeave);
                        payAmt = payAmt.subtract(eachLeave);
                    }

                }
                // 数据清理
                vo.setMarketPrice(null);
                vo.setMarketPriceVip(null);
                vo.setMarPrice(null);
                vo.setSupplierPrice(null);
                totalAmt = totalAmt.add(totalPrice);
                payAmt = payAmt.add(totalPrice);
            }
        }

        //总价
        // C 端包邮 499 B端包邮299
        BigDecimal exemptionPostage = OrderConstant.EXEMPTION_POSTAGE_B;
        if (CommonConstant.PLATFORM_TYPE_C.equals(platformType)) {
            exemptionPostage = OrderConstant.EXEMPTION_POSTAGE_C;
        }
        // 根据付款价格计算邮费
        if (payAmt.compareTo(exemptionPostage) >= 0) {
            postAmt = BigDecimal.ZERO;
        } else {
            payAmt = payAmt.add(postAmt);
        }

        Map<String, Object> map = Maps.newHashMap();

        if (needAddr) {
            //获取用户上次订单信息
            CusOrderAddressVO address = cusOrderAddressMapper.getLatestInfo(userId);
            map.put(ADDRESS, address);
        }

        map.put(CARTLIST, cartList);
        map.put(LEAVEAMT, leaveAmt);
        map.put(PAYAMT, payAmt);
        map.put(TOTALAMT, totalAmt);
        map.put(POSTAMT, postAmt);
        map.put(TAXAMT, taxAmt);
        map.put(NEEDIDCARD, needID);

        return map;
    }

    /**
     * @param dto
     * @return 返回类型
     * @throws
     * @Title: submitOrderClientWithTx
     * @Description: C端订单提交
     * @author diaoxingguo
     * @date 2018年6月16日
     */
    @Override
    @Transactional
    public CusOrderMasterTableVO submitOrderClientWithTx(CusOrderMasterDTO dto, Long shopId, Long userId) {
        List<Long> cartIds = dto.getCartIds();
        CusOrderAddressVO addr = dto.getAddress();

        // 获取购物车商品信息
        List<CartVO> cartList = this.getCartList(cartIds, userId, addr.getIdCard(), shopId, CommonConstant.PLATFORM_TYPE_C);

        // 获取上级商品的成本
        Map<Long, CartVO> supList = this.getParentProductInfo(shopId, userId, cartIds, CommonConstant.PLATFORM_TYPE_C);

        //删除购物车
        this.deleteCart(shopId, userId, cartIds);

        //通过shopId获取店铺主人的信息
        UserInfo userInfo = getShopUserInfo(shopId);
        Boolean isVip = userInfo.isVip();
        String shopName = userInfo.getShopInfo().getName();
        List<String> openIds = Lists.newArrayList(userInfo.getWxOpenId());

        //商品总价
        BigDecimal totalAmt = BigDecimal.ZERO;
        //优惠总价
        BigDecimal leaveAmt = BigDecimal.ZERO;
        //邮费
        BigDecimal postAmt = OrderConstant.POST_AMT;
        //税费
        BigDecimal taxAmt = BigDecimal.ZERO;
        //总利润
        BigDecimal totalProfitAmt = BigDecimal.ZERO;

        //获取优惠券
        Map<Long, CusCoupon> couponMap = Maps.newHashMap();
        List<Long> tpidList = cartList.stream().map(CartVO::getProductId).collect(Collectors.toList());
        couponMap = cusCouponService.getMapByTpids(tpidList, userId, shopId);

        //pl_product商品列表
        List<PlProduct> plProductList = Lists.newArrayList();
        //优惠券idList
        List<Long> couponIdList = Lists.newArrayList();

        //费用计算
        Integer totalNum = 0;
        for (CartVO vo : cartList) {
            BigDecimal price = vo.getSellPrice().compareTo(vo.getCounterPrice()) >= 0 ? vo.getSellPrice() : vo.getCounterPrice();
            Integer num = (null != vo.getNum()) ? vo.getNum() : 0;
            BigDecimal totalPrice = price.multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP);
            CusCoupon cuscoupon = couponMap.get(vo.getProductId());
            BigDecimal couponAmt = BigDecimal.ZERO;

            //成本价
            if (isVip && null != vo.getMarketPriceVip()) {
                vo.setMarPrice(vo.getMarketPriceVip());
            } else {
                vo.setMarPrice(vo.getMarketPrice());
            }

            BigDecimal profitUnitAmt = price.subtract(vo.getMarPrice());
            //优惠券判断
            if (null != cuscoupon) {
                //单个利润计算:售价-优惠券-成本价

                if (cuscoupon.getAmt().compareTo(BigDecimal.ZERO) > 0 &&
                        profitUnitAmt.subtract(cuscoupon.getAmt()).compareTo(BigDecimal.ZERO) > 0) {
                    couponAmt = cuscoupon.getAmt();
                    BigDecimal leaveUnitAmt = couponAmt.multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    vo.setCouponId(cuscoupon.getId());
                    vo.setCouponAmt(leaveUnitAmt);
                    //优惠金额
                    leaveAmt = leaveAmt.add(leaveUnitAmt);
                    //利润
                    profitUnitAmt = profitUnitAmt.subtract(cuscoupon.getAmt());
                    couponIdList.add(cuscoupon.getId());
                } else {
                    //不满足，移除
                    couponMap.remove(vo.getProductId());
                }

            }

            vo.setProfitAmt(profitUnitAmt.multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP));
            totalProfitAmt = totalProfitAmt.add(vo.getProfitAmt());

            totalAmt = totalAmt.add(totalPrice);

            totalNum = totalNum + vo.getNum();
            PlProduct plProduct = new PlProduct();
            plProduct.setId(vo.getPpid());
            plProduct.setStockNum(vo.getNum());
            plProductList.add(plProduct);
        }

        //总价
        if (totalAmt.subtract(leaveAmt).compareTo(OrderConstant.EXEMPTION_POSTAGE_C) >= 0) {
            postAmt = BigDecimal.ZERO;
        }

        //实付价
        BigDecimal payAmt = totalAmt.subtract(leaveAmt).add(postAmt);

        //更改商品库存和销量
        this.updateStockAndSellNum(plProductList);
        //删除优惠券
        this.deleteCoupon(couponIdList);

        Date date = new Date();
        //先保存地址
        CusOrderAddress address = BeanUtils.copyProperties(addr, CusOrderAddress.class);
        address.setUserId(userId);
        address.setCreatedAt(date);
        cusOrderAddressMapper.save(address);


        //保存order主表
        CusOrderMaster so = this.saveCusOrderMaster(
                userId, shopId, address.getId(), totalAmt, postAmt,
                payAmt, taxAmt, totalNum, dto, totalProfitAmt,
                leaveAmt, CommonConstant.PLATFORM_TYPE_C
        );
        // C端需要修改新订单标记
        Shop shop = new Shop();
        shop.setId(shopId);
        shop.setNewOrder(1);
        shop.setUpdatedAt(date);
        shopMapper.updateByPrimaryKeySelective(shop);

        Long soId = so.getId();
        String orderCode = so.getOrderId();

        //保存order_item表
        List<CusOrderDetail> itemList = Lists.newArrayList();
        String mpName = "";
        for (CartVO vo : cartList) {
            CusOrderDetail soItem = new CusOrderDetail();
            soItem.setPid(soId);
            soItem.setShopId(shopId);
            soItem.setCustomId(userId);
            soItem.setMchName(vo.getName());
            soItem.setPpid(vo.getPpid());
            soItem.setMchImg(vo.getMainImageUrl());
            soItem.setMchDesc(vo.getUnitDesc());
            soItem.setCouponId(vo.getCouponId());
            soItem.setCouponAmt(vo.getCouponAmt());
            soItem.setUnitAmt(vo.getSellPrice().compareTo(vo.getCounterPrice()) >= 0 ? vo.getSellPrice() : vo.getCounterPrice());
            soItem.setSupplierPrice(vo.getSupplierPrice());
            soItem.setProfitAmt(vo.getProfitAmt());
            soItem.setMarketPrice(vo.getMarPrice());

            BigDecimal price = vo.getSellPrice().compareTo(vo.getCounterPrice()) >= 0 ? vo.getSellPrice() : vo.getCounterPrice();
            Integer num = (null != vo.getNum()) ? vo.getNum() : 0;
            BigDecimal totalPrice = price.multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP);
            CusCoupon cuscoupon = couponMap.get(vo.getProductId());
            BigDecimal leaveUnitAmt = BigDecimal.ZERO;
            if (null != cuscoupon) {
                leaveUnitAmt = cuscoupon.getAmt().multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP);
            }
            soItem.setTotalAmt(totalPrice);
            soItem.setCouponAmt(leaveUnitAmt);
            soItem.setTaxAmt(taxAmt);
            soItem.setNum(vo.getNum());
            soItem.setStatus(STATUS_WAIT);
            soItem.setCreatedAt(date);
            soItem.setpShopId(0L);
            soItem.setpProfitAmt(new BigDecimal(0));
            mpName = StringConcatUtils.concatString(mpName, vo.getName(), CommonConstant.CONCAT_LENGTH_30);

            // 超级合伙人利润处理
            this.setSuperProfit(supList, vo, soItem, num, so);

            itemList.add(soItem);
        }

        // 更新主表字段
        this.updateCusOrderMaster(so);

        cusOrderDetailMapper.batchInsert(itemList);

        CusOrderMasterTableVO resultSo = this.handleResult(totalAmt, postAmt, payAmt, taxAmt, orderCode, address.getId(),
                shopId, userId, dto.getRemark(), soId, totalNum);

        //异步发送消息
        //管理员消息
        wxMsgService.sendOrderMsgToAdminWithUserId(shopName, userId, mpName, totalAmt);
        //定制师消息
        wxMsgService.sendOrderMsgToTailor(openIds, userId, mpName, totalProfitAmt, soId, dto.getRemark());

        return resultSo;
    }

    //订单主表保存
    private CusOrderMaster saveCusOrderMaster(
            Long userId, Long shopId, Long addrId, BigDecimal totalAmt, BigDecimal postAmt,
            BigDecimal payAmt, BigDecimal taxAmt, Integer num, CusOrderMasterDTO dto, BigDecimal totalProfitAmt,
            BigDecimal leaveAmt, Integer platformType) {
        Date date = new Date();
        //保存order主表
        CusOrderMaster so = new CusOrderMaster();
        so.setShopId(shopId);
        so.setAddressId(addrId);
        so.setCustomId(userId);
        so.setMchAmt(totalAmt);
        so.setPostAmt(postAmt);
        so.setPayAmt(payAmt);
        so.setStatus(STATUS_WAIT);
        so.setTaxAmt(taxAmt);
        so.setCreatedAt(date);
        so.setRemark(dto.getRemark());
        so.setRecordTime((int) (System.currentTimeMillis() / 1000));
        so.setFormIdCreate(dto.getFormIdCreate());
        so.setpProfitAmt(new BigDecimal(0));
        so.setpShopId(0L);
        if (null != totalProfitAmt) {
            so.setProfitAmt(totalProfitAmt);
        }
        if (null != leaveAmt) {
            so.setCouponAmt(leaveAmt);
        }
        so.setNum(num);
        so.setPlatformType(platformType);
        cusOrderMasterMapper.save(so);
        return so;
    }

    /**
     * 补充主表数据
     * 订单id
     * 超级合伙人店铺id
     * 超级合伙人利润
     *
     * @param so
     */
    private void updateCusOrderMaster(CusOrderMaster so) {
        // 更新主表字段
        so.setOrderId(OrderCodeUtil.getOrderId(so.getId()));
        CusOrderMaster orderUpdate = new CusOrderMaster();
        orderUpdate.setId(so.getId());
        orderUpdate.setOrderId(so.getOrderId());
        orderUpdate.setpShopId(so.getpShopId());
        orderUpdate.setpProfitAmt(so.getpProfitAmt());
        cusOrderMasterMapper.updateByPrimaryKeySelective(orderUpdate);
    }

    //更改商品库存和销量
    private void updateStockAndSellNum(List<PlProduct> plProductList) {
        if (CollectionUtils.isNotEmpty(plProductList)) {
            int rows = plProductMapper.updateStockAndSellNum(plProductList);
            if (rows < 1) {
                //获取库存不足的商品名
                String name = plProductMapper.getLackStockName(plProductList);
                throw new VisibleException(CodeEnum.PRODUCT_STOCK_NUM_LT_0.getCode(), name);
            }
        }
    }

    //获取购物车信息
    private List<CartVO> getCartList(List<Long> cartIds, Long userId, String idCard, Long shopId, Integer platformType) {
        //获取购物车对应的商品信息
        List<CartVO> cartList = this.cartMapper.listProduct(cartIds, userId, shopId, platformType);
        if (CollectionUtils.isEmpty(cartList)) {
            throw new VisibleException(CodeEnum.PRODUCT_NOT_EXIST);
        }

        //需要身份证号
        Boolean needID = true;

        //如果全部在国内，不需要身份证号
        List<CartVO> outProductList = cartList.stream().filter(item -> ProductConstant.STOCK_AREA_OUT.equals(item.getStockArea())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(outProductList)) {
            needID = false;
        }

        //校验身份证号
        if (needID && !IdcardValidator.isValidatedAllIdcard(idCard)) {
            throw new VisibleException(CodeEnum.IDCARD_ERROR);
        }

        cartList.stream().forEach(vo -> {
            if (vo.getStockNum() < vo.getNum()) {
                throw new VisibleException(CodeEnum.PRODUCT_STOCK_NUM_LT_0.getCode(), vo.getName());
            }
        });

        return cartList;
    }

    //删除购物车
    private void deleteCart(Long shopId, Long userId, List<Long> cartIds) {
        //删除购物车
        CartDTO cartDTO = new CartDTO();
        cartDTO.setSid(shopId);
        cartDTO.setUid(userId);
        cartDTO.setIds(cartIds);
        int rows = this.cartMapper.deleteByIds(cartDTO);
        if (rows < cartIds.size()) {
            throw new VisibleException(CodeEnum.PRODUCT_STOCK_NUM_LT_0);
        }
    }

    private CusOrderMasterTableVO handleResult(BigDecimal totalAmt, BigDecimal postAmt, BigDecimal payAmt,
                                               BigDecimal taxAmt, String orderCode, Long addrId, Long shopId, Long userId, String remark,
                                               Long soId, Integer num) {
        CusOrderMasterTableVO resultSo = new CusOrderMasterTableVO();
        Date date = new Date();
        resultSo.setPay_amt(payAmt);
        resultSo.setStatus(STATUS_WAIT);
        resultSo.setOrder_id(orderCode);
        resultSo.setAddress_id(addrId);
        resultSo.setShop_id(shopId);
        resultSo.setMch_amt(totalAmt);
        resultSo.setPost_amt(postAmt);
        resultSo.setTax_amt(taxAmt);
        resultSo.setRecord_time((int) (System.currentTimeMillis() / 1000));
        resultSo.setNum(num);
        resultSo.setCustom_id(userId);
        resultSo.setRemark(remark);
        resultSo.setCreated_at(date);
        resultSo.setUpdated_at(date);
        resultSo.setId(soId);
        resultSo.setPay_type(PAY_TYPE_WX);
        return resultSo;
    }

    //通过shopId获取店铺主人的信息
    private UserInfo getShopUserInfo(Long shopId) {
        UserInfo userInfo = this.getUserInfoByShopId(shopId);
        return userInfo;
    }

    //删除优惠券
    private void deleteCoupon(List<Long> couponIdList) {
        if (CollectionUtils.isNotEmpty(couponIdList)) {
            cusCouponMapper.deleteByIds(couponIdList);
        }

    }

    /**
     * 获取上级 购物车商品对应的成本
     *
     * @param shopId
     * @param userId
     * @param cartIds
     * @param platformType
     * @return
     */
    private Map<Long, CartVO> getParentProductInfo(Long shopId, Long userId, List<Long> cartIds, Integer platformType) {
        Map<Long, CartVO> result = new HashMap<>();
        // 检查父级 超级合伙人
        ShopVO s = shopMapper.selectById(shopId);
        if (null == s) {
            // 店铺不存在
            throw new VisibleException(CodeEnum.SHOP_NOT_EXIST.getCode(), "店铺不存在");
        }
        // 不存在上级
        if (null == s.getParentId() || s.getParentId() <= 0) {
            return result;
        }
        List<CartVO> cartList = this.cartMapper.listParentProduct(cartIds, userId, s.getParentId(), platformType);
        for (CartVO tmp : cartList) {
            // 超级合伙人店铺id
            tmp.setShopId(s.getParentId());
            result.put(tmp.getPpid(), tmp);
        }

        return result;
    }

    /**
     * 处理订单主表子表的 超级合伙人分成
     *
     * @param supList
     * @param vo
     * @param soItem
     * @param num
     * @param so
     */
    private void setSuperProfit(Map<Long, CartVO> supList, CartVO vo, CusOrderDetail soItem, Integer num, CusOrderMaster so) {
        CartVO supCart = supList.get(vo.getPpid());
        if (null != supCart) {
            BigDecimal supUnitProfitAmt = soItem.getMarketPrice().subtract(supCart.getMarketPrice());
            soItem.setpShopId(supCart.getShopId());
            soItem.setpProfitAmt(supUnitProfitAmt.multiply(new BigDecimal(num)).setScale(2, BigDecimal.ROUND_HALF_UP));

            so.setpShopId(supCart.getShopId());
            so.setpProfitAmt(so.getpProfitAmt().add(soItem.getpProfitAmt()));
        }
    }

}